﻿using System;
using System.Collections.Generic;

namespace Activity.II
{
	/// <summary>
	/// Тип делегата для фиксирования высокой нагрузки сервера.
	/// </summary>
	public delegate void LoadWarningDelegate(object sender, float load);

	/// <summary>
	/// Центральный процессор для хостинга игрового сервера.
	/// </summary>
	public class Mainframe : Computer
	{
		/// <summary>
		/// Событие, возникающее при большой нагрузки сервера.
		/// </summary>
		public event LoadWarningDelegate LoadWarning;

		// Текст последней ошибки
		protected string lastError;

		/// <summary>
		/// Создать новый экземпляр сервера.
		/// </summary>
		/// <param name="name">Название сервера.</param>
		public Mainframe (string name) : base(name)
		{
			foreach (int error in Enum.GetValues(typeof(Error)))
			{
				switch ((Error)error)
				{
					case Error.NotFound:
					case Error.RequestTimeout:
					case Error.BandwidthLimitExceeded:
					case Error.ServiceUnavailable:
					case Error.GatewayTimeout:
					case Error.BadRequest:
						// Данные ошибки не возникают при использовании мейнфрейма
						break;

					default:
						errors.Add(error);
						break;
				}
			}

			// Случайное число максимального количества игроков в заданных пределах [50;109]
			var next = random.Next(50, 110);

			// Округляем число вниз по модулю 10 [50;200]
			var maxPlayers = next - next % 10;
			Players = new List<string>(maxPlayers);
		}

		/// <summary>
		/// Подключить игрока к серверу.
		/// </summary>
		/// <param name="playerName">Имя игрока.</param>
		/// <returns>Истина при успешном подключении, в противном случае ложь.</returns>
		public override bool Connect (string playerName)
		{
			// Зашита от перегрузок
			if (Players.Count >= Players.Capacity)
			{
				Log(string.Format("Невозможно подключить игрока {0}: нету свободных мест", playerName));
				return false;
			}

			// Предупреждение о перегрузках
			if (GetLoad() >= 0.8f)
			{
				// Фиксируем предупреждение
				Log(string.Format("Предупреждение: сервер работает при критической нагрузке {0:0}%!", GetLoad() * 100));
				// Вызываем событие
				if (LoadWarning != null) LoadWarning(this, GetLoad());

			}

			// 10% вероятность ошибки при подключении
			var hasError = new Random().Next(0, 100) < 10;
			if (hasError)
			{
				// Фиксируем ошибку 
				lastError = CreateError();
				Log(lastError);
			}
			else
			{
				// Добавляем игрока в список
				Players.Add(playerName);
				// Фиксируем подключение 
				Log(string.Format("Игрок {0} подключился к игре!", playerName));
			}

			// Возвращаем результат
			return hasError;
		}

		/// <summary>
		/// Текстовое представление данного объекта.
		/// </summary>
		public override string ToString ()
		{
			return string.Format("Тип: Мейнфрейм") +
				   string.Format("\r\nИгроков: [{0}/{1}]", Players.Count, Players.Capacity) +
				   string.Format("\r\nНагрузка: {0:00}%", GetLoad() * 100) +
				   string.Format("\r\nОшибка: {0}", lastError);
		}
	}
}
